﻿var janus = null;
var sfutest = null;
var opaqueId = "videoroom-"+Janus.randomString(12);
var opaqueIdScreen = "videoroom-"+Janus.randomString(12);
var screentest = null;
var capture = null;

var myroom = 1234;	// Demo room

var myusername = "test001";
var screenUsr = "_screenShare_";

var myid = null;
var mystream = null;
var localDiv = null;
		// We use this other ID just to map our subscriptions to us
var mypvtid = null;
var feeds = [];
var bitrateTimer = [];
var doSimulcast = false;//(getQueryStringValue("simulcast") === "yes" || getQueryStringValue("simulcast") === "true");
var doSimulcast2 = false;//(getQueryStringValue("simulcast2") === "yes" || getQueryStringValue("simulcast2") === "true");
var subscriber_mode = false;//(getQueryStringValue("subscriber-mode") === "yes" || getQueryStringValue("subscriber-mode") === "true");

//event type
var SZW_unknownError = "SZW_unknownError";
var SZW_user_enter = "SZW_user_enter"; /// param is the id of user.
var SZW_user_leave = "SZW_user_leave";
var SZW_holder_mute = "SZW_holder_mute";
var SZW_room_destroy = "SZW_room_destroy";
var SZW_error_noRoom = "SZW_error_noRoom";
var SZW_error_device = "SZW_error_device";


var sdk = (function(){

		var that = this;
		this.userID = "";
		this.videoType = "";
		this.channel = "";
		this.role = "1";
		this.projectId = "";
		this.secret = "E3ULXDeId0xP6RZVGFgF7hbxPctRoDOz";
		this.appId = "zhzc2021nsb";
		this.roomId = 123456; //from mgr
		this.callback = "";

		this.server = null;
		this.idTagMap = new Map(); //map[userID, videoTag], for cleaning up
		this.maxMan = 10;

		//服务端访问接口
		var apis = {
			createRoom             : "",
			destroyRoom            : "https://gslb.zzgx.gov.cn/platform-admin/req/liveStreamSwitch?",
			unInit                 : "http://127.0.0.1:8899/fwLive?action=unInit",
			getRtcRoom	       : "https://gslb.zzgx.gov.cn/platform-admin/req/clientInit?",
			startPushStream        : "http://127.0.0.1:8899/fwLive?action=startPushStream&param=",
			stopPushStream         : "http://127.0.0.1:8899/fwLive?action=stopPushStream&param=",
			getProjectLiveUrls     : "https://gslb.zzgx.gov.cn/platform-admin/req/getLive?",
			getProjectReviewUrls   : "https://gslb.zzgx.gov.cn/platform-admin/req/getTVod?",
			getProjectLiveUrlsIE   : "https://gslb.zzgx.gov.cn/platform-admin/req/getLive?",
			getProjectReviewUrlsIE : "https://gslb.zzgx.gov.cn/platform-admin/req/getTVod?",
			startMixStream         : "https://gslb.zzgx.gov.cn/platform-admin/req/interactivity?",
			stopMushStream         : "https://gslb.zzgx.gov.cn/platform-admin/req/interactivity?",
			queryDevices           : "http://127.0.0.1:8899/fwLive?action=queryDevices",
			getSecret              : "",
			getPublishStream       : "https://gslb.zzgx.gov.cn/platform-admin/req/webrtcCallBack?",
			getStopStream          : "https://gslb.zzgx.gov.cn/platform-admin/req/stopOne?",
			muteOther			   : "https://gslb.zzgx.gov.cn/platform-admin/req/muteOther?",
			addUser				   : "https://gslb.zzgx.gov.cn/platform-admin/req/setAttendeeIDs?",
		};


	    //初始化
		var _init = function(appid, sdkobj, suc, err){
			if(appid !== null &&appid !== "")
				appId = appid;
			this.maxMan = 10; ///determined by server
			return this;
		};

		//请求公钥
		var _getSecret = function(suc, err){
			//调用服务端接口完成业务处理
			$.get(apis.getSecret,function(data,status){
				this.secret = " ";
			});

		};


		//释放
		var _unInit = function(suc, err){
			if(option.videoType !== 3)
			{
				//调用服务端接口完成业务处理
				$.get(apis.unInit,function(data,status){
					suc(data);
				});
			}
			else
			{
				//no action for rtc
			}

		};

		//创建直播房间
		var _createRoom = function(projectID , suc, err){
			suc(true);
			this.projectId = projectID;

		};

		//关闭直播房间
		var _destroyRoom = function(userId, projectID, suc, err){
			//html should have checked user type already, ignore userId.
			//调用服务端接口完成业务处理
			var signature = _md5("projectId=" + projectID + "&");

			$.get(apis.destroyRoom + "projectId=" + projectID + "&" +signature,function(data,status){
				if(suc)
					suc(data);
			});
			selfJanusId = 0;
			selfSessionId = 0;
			selfHandler = 0;
			selfRoomId = 0;

		};

		//设置回调函数
		var _setStatusCallback = function(callback, suc, err){
			//save callback
			sdk.callback = callback;

		};

		//申请房间，再开始推流，no security at all.
		var _startPushStreamV2 = function(option, suc, err){
			//根据option.videoType确定怎么推流。
			if(option.videoType === 3)//rtc
			{
				var params = "";
				for (var key in option)
				{
					//params += "&"
					var str = key + "=" +  option[key];
					if(key === "userId")
						myusername = option[key];
					if(key === "projectId")
						this.projectId = option[key];
					params += str + "&";
				}
				var signature = _md5(params);
				params += signature;
				var api = apis.getRtcRoom + params;// + "&" + getTimeStamp();
				//调用服务端接口完成业务处理
				$.get(api,function(data,status){
					if(data !==""){
						var ret = data;
						if(ret.result !== "success") {
							console.log("failed to get room from mgr");
							suc(false);
							return;
						}
						suc(true);  //for roomid,
						///start work for webrtc
						//parse json string {"result":"success","videoInfo":{"pushId":11,"pushUrl":"rtmp://39.98.124.180:1936/live/01/1221/PCCamera_11","webrtcRoomId":1619544000,"liveRoomId":"01","userType":1,"projectId":1221,"webrtcServer":"rtv.com"}}
						//var roomid = 1234; //ret.videoInfo.webrtcRoomId;
						var roomid = ret.videoInfo.webrtcRoomId;
						//var serverIn = "media1.zzgx.gov.cn";//ret.videoInfo.webrtcServer;
						var serverIn = ret.videoInfo.webrtcServer;
						this.rooId = roomid;
						this.server = serverIn;
						startRTCStream(roomid, serverIn, myusername);
					}

				});
			}
			else
			{
				var params = "";
				for (var key in option)
				{
					var str = key + "=" +  option[key] + "|||";
					params += str;
				}
				var api = apis.startPushStream + params + getTimeStamp();
				//调用服务端接口完成业务处理
				$.get(api,function(data,status){
					if(data !=="" && (JSON.parse(data)).Result === 0){
						suc(true);
					}

				});
			}


		};




		//直播开始
		var _startPushStream = function(option, suc, err){
				var params = "";
				for (var key in option)
				{
					var str = key + "=" +  option[key] + "|||";
					params += str;
				}
				var api = apis.startPushStream + params + getTimeStamp();
				//调用服务端接口完成业务处理
				$.get(api,function(data,status){
					if(data !=="" && (JSON.parse(data)).Result === 0){
						suc(true);
					}

				});

		};

		//停止直播
		var _stopPushStream = function(option, suc, err){
			//for webrtc, stop it.
			if(option.videoType  ===3)
			{
				_unpublish(option.userId, suc, err);
				//调用MGR
				var params = "projectId=" + option.projectId + "&roomId=" + selfRoomId + "&userId=" + option.userId;// + "&appId=" + appId;
					 var signature = _md5(params + "&");
					 $.get(apis.getStopStream + params + "&" + signature, function(data,status){
					       if(data !=="" && (data.result === "success")){
					            suc(true);
					      }
					      else
          			     {
							Janus.error("failed to getStopStream");
					      }
					   });
				return;
			}

			var params = "";
			for (var key in option)
			{
				var str = key + "=" +  option[key] + "|||";
				params += str;
			}
			var api = apis.stopPushStream + params + getTimeStamp();
			//调用服务端接口完成业务处理
			$.get(api,function(data,status){
				if(JSON.parse(data).Result === 0){
					suc(true);
				}

			});

		};

		//查询直播地址
		var _getProjectLiveUrls = function(projectID, isMixStream, suc, err){

			//调用服务端接口完成业务处理
			var signature = _md5("projectId=" + projectID + "&");

			var api = apis.getProjectLiveUrls + "projectId=" + projectID + "&" + signature  ;

			$.get(api ,function(res,status){

				var result = JSON.parse(res);

				if(result.result !== "success"){
					suc(false);
					return;
				}
				if(result.videoRoomInfoArray.length === 0 || result.videoRoomInfoArray[0].videoInfoArray.length === 0){
					suc(false);
					return;
				}
				var returnUrl = "";
				var arr = result.videoRoomInfoArray[0].videoInfoArray;
				if(isMixStream){
					for(var i =0;i<arr.length;i++){
						if(arr[i].isInteractive === 1){
							returnUrl = arr[i].playUrl;
							break;
						}
					}
				}else{
					for(var i =0;i<arr.length;i++){
						if(arr[i].isInteractive === 0){
							returnUrl = arr[i].playUrl;
							break;
						}
					}
				}
				suc(returnUrl);


			});

		};

		//查询回看地址
		var _getProjectReviewUrls = function(projectID, startTime, stopTime, suc, err){
			//调用服务端接口完成业务处理
			var signature = _md5("projectId=" + projectID + "&");
			var api = apis.getProjectReviewUrls + "projectId=" + projectID + "&" + signature ;
			$.get(api ,function(res,status){

				var result = JSON.parse(res);

				if(result.result === "success"){
					suc(result.videoRoomInfoArray[0].videoInfoArray);
				}
			});
		};
		//混流开始
		var _startMixStream = function(option, suc, err){

			var params = "";
			for (var key in option)
			{
				var str = key + "=" +  option[key] + "&";
				params += str;
			}
			var signature = _md5(params);
			var api = apis.startMixStream + params +  signature;
			//调用服务端接口完成业务处理
			$.get(api,function(data,status){
				if(data !=="" && (JSON.parse(data)).Result === 0){
					suc(true);
				}

			});
		};

		//停止混流
		var _stopMixStream = function(option, suc, err){
			var params = "";
			for (var key in option)
			{
				var str = key + "=" +  option[key] + "&";
				params += str;
			}
			const signature = _md5(params);
			var api = apis.stopMixStream + params +  signature;

			//调用服务端接口完成业务处理
			$.get(api,function(data,status){
				if(JSON.parse(data).Result === 0){
					suc(true);
				}

			});

		};

		//获取设备信息
		var _queryDevices = function(suc, err){

			var api = apis.queryDevices + "&" + getTimeStamp();
			//调用服务端接口完成业务处理
			$.get(api,function(data,status){
				if(JSON.parse(data).Result === 0){
					var result = JSON.parse(data).VideoDevices;
					if(result.length > 0){
						suc(result);
					}else{
						err("设备数为0");
					}


				}

			});

		};

//for holders usage
function muteOther(targetUserId, muteAudio, muteVideo, suc, err){
	var params = "";
	params = "usrId=" + myusername + "&targetUsrId=" + targetUserId + "&roomId=" + selfRoomId + "&projectId=" + sdk.projectId + "&muteVideo=" + muteVideo + "&muteAudio=" + muteAudio +
		"&session=" + selfSessionId + "&handle=" + selfHandler + "&publisherId=" + selfJanusId + "&";
	var signature = _md5(params);
	var api = apis.muteOther + params +  signature;
	//调用服务端接口完成业务处理
	$.get(api,function(data,status){
		if(data !=="" && (data.code === 0)){
			suc(true);
		}
	});
}
//muteAudio: 0:unmute, 1, mute, -1: untouch
function _mute(userId, muteAudio, suc, err){
	if(userId !== myusername)
	{
		Janus.log("call backend for muting/unmuting others: targetUsrId=" + userId + "&UsrId=" + myusername + "&roomId=" + selfRoomId + "&projectId=" + sdk.projectId);
		muteOther(userId, muteAudio, -1,suc, err);
		return;
	}
	var muted = sfutest.isAudioMuted();
	Janus.log((muteAudio ? "muting" : "Unmuting") + " local stream audio...");
	if(muteAudio === 1)
		sfutest.muteAudio();
	else if(muteAudio === 0)
		sfutest.unmuteAudio();
	else
		Janus.error("mute: unsupported muteAudio=" + muteAudio);
	muted = sfutest.isAudioMuted();
}
//muteVideo: 0:unmute, 1, mute, -1: untouch
function _videoMute(userId, muteVideo, suc, err){
	if(userId !== myusername)
	{
		Janus.log("call backend for video muting/unmuting others: targetUsrId=" + userId + "&UsrId=" + myusername + "&roomId=" + selfRoomId + "&projectId=" + sdk.projectId);
		muteOther(userId, -1, muteVideo,suc, err);

		return;
	}
	var mutedVideo = sfutest.isVideoMuted();
	Janus.log((muteVideo ? "muting" : "Unmuting") + " local stream video...");
	if(muteVideo === 1)
		sfutest.muteVideo();
	else if(muteVideo === 0)
		sfutest.unmuteVideo();
	else
		Janus.error("mute video: unsupported muteVideo=" + muteVideo);
	mutedVideo = sfutest.isVideoMuted();
}
//keep old interface.
function _toggleMute(userId, suc, err){
	Janus.error("toggle mute is obsoleted, try mute. ");
	if(userId !== myusername)
	{
		Janus.log("now, just support toggle mute audio for self.");
		return;
	}
	var muted = sfutest.isAudioMuted();
	Janus.log((muted ? "Unmuting" : "Muting") + " local stream audio...");
	if(muted)
		sfutest.unmuteAudio();
	else
		sfutest.muteAudio();
	muted = sfutest.isAudioMuted();
}

function _toggleVideoMute(userId, suc, err){
	Janus.error("toggle video mute is obsoleted, try video mute. ");
	if(userId !== myusername)
	{
		Janus.log("now, just support toggle video mute for self.");
		return;
	}
	var mutedVideo = sfutest.isVideoMuted();
	Janus.log((mutedVideo ? "Unmuting" : "Muting") + " local stream video...");
	if(mutedVideo)
		sfutest.unmuteVideo();
	else
		sfutest.muteVideo();
	mutedVideo = sfutest.isVideoMuted();
}
function _unpublish(userId, suc, err){
	if(userId !== myusername)
	{
		Janus.log("now, just support unpublishing self.");
		return;
	}
	unpublishOwnFeed();
}

function unpublishOwnFeed() {
	// Unpublish our stream
	var unpublish = { request: "unpublish" };
	sfutest.send({ message: unpublish });
}


var getTimeStamp = function(){
	var timestamp = new Date().getTime();
	return "v=" + timestamp;
}

var _md5 = function(str){
	var timestamp = getTimeStamp();
	return timestamp + "&appId=" + this.appId + "&signature="+ md5(str + timestamp + "&appId=" + this.appId + "&secret=" + this.secret)  ;
}

///////////////////////////////////////

function startRTCStream(roomid, serverIn, userId) {
	myroom = roomid;
	server = "wss://" + serverIn + ":8989";
	myusername = userId;
	// Initialize the library (all console debuggers enabled)
	Janus.init({debug: "all", callback: function() {
		// Use a button to start the demo
			// Make sure the browser supports WebRTC
			if(!Janus.isWebrtcSupported()) {
				console.error("No WebRTC support... ");
				return;
			}
			// Create session
			janus = new Janus(
				{
					server: server,
					success: function() {
						// Attach to VideoRoom plugin
						janus.attach(
							{
								plugin: "janus.plugin.videoroom",
								opaqueId: opaqueId,
								success: function(pluginHandle) {
									sfutest = pluginHandle;
									Janus.log("Plugin attached! (" + sfutest.getPlugin() + ", id=" + sfutest.getId() + ")");
									Janus.log("  -- This is a publisher/manager");

									//register user
									var register = {
										request: "join",
										room: myroom,
										ptype: "publisher",
										display: myusername
									};
									sfutest.send({ message: register });
								},
								error: function(error) {
									Janus.error("  -- Error attaching plugin...", error);
									if(sdk.callback)
										sdk.callback(SZW_unknownError, error);
								},
								consentDialog: function(on) {
									Janus.debug("Consent dialog should be " + (on ? "on" : "off") + " now");
								},
								iceState: function(state) {
									Janus.log("ICE state changed to " + state);
								},
								mediaState: function(medium, on) {
									Janus.log("Janus " + (on ? "started" : "stopped") + " receiving our " + medium);
								},
								webrtcState: function(on) {
									Janus.log("Janus says our WebRTC PeerConnection is " + (on ? "up" : "down") + " now");
									if(!on)
										return;
								},
								onmessage: function(msg, jsep) {
									Janus.debug(" ::: Got a message (publisher) :::", msg);
									var event = msg["videoroom"];
									Janus.debug("Event: " + event);
									if(event) {
										if(event === "joined") {
											// Publisher/manager created, negotiate WebRTC and attach to existing feeds, if any
											myid = msg["id"];
											mypvtid = msg["private_id"];
											Janus.log("Successfully joined room " + msg["room"] + " with ID " + myid);
											if(subscriber_mode) {
												Janus.log("just subscriber_mode: " + msg["room"] + " with ID " + myid);
											} else {
												Janus.log("before notification: selfSession=" + selfSessionId + ", selfHandler=" + sfutest.getId() + ", selfJanusId=" + myid + ", selfRoomId=" + selfRoomId + ", projectId=" + sdk.projectId + ", outside usrId=" + myusername);
												 //调用MGR
											var params = "selfHandler=" + sfutest.getId() + "&selfRoomId=" + selfRoomId + "&selfSession=" + selfSessionId + "&outsideUserId=" + myusername + "&selfPublishId=" + myid + "&projectId=" + sdk.projectId;// + "&appId=" + appId;
												 var signature = _md5(params + "&");
												 $.get(apis.getPublishStream + params + "&" + signature, function(data,status){
												       if(data !=="" && (data.result === "success")){
												            suc(true);
												      } else {
														Janus.error("failed to getPublishedStream");
												      }
												   });
												publishOwnFeed(true);
											}
											// Any new feed to attach to?
											if(msg["publishers"]) {
												var list = msg["publishers"];
												Janus.debug("Got a list of available publishers/feeds:", list);
												for(var f in list) {
													var id = list[f]["id"];
													var display = list[f]["display"];
													var audio = list[f]["audio_codec"];
													var video = list[f]["video_codec"];
													Janus.debug("  >> [" + id + "] " + display + " (audio: " + audio + ", video: " + video + ")");
													newRemoteFeed(id, display, audio, video);
												}
											}
										} else if(event === "destroyed") {
											// The room has been destroyed
											Janus.warn("The room has been destroyed!");
											if(sdk.callback)
												sdk.callback(SZW_room_destroy);
											///clean up map
											sdk.idTagMap.clear();

										} else if(event === "event") {
											// Any new feed to attach to?
											if(msg["publishers"]) {
												var list = msg["publishers"];
												Janus.debug("Got a list of available publishers/feeds:", list);
												for(var f in list) {
													var id = list[f]["id"];
													var display = list[f]["display"];
													var audio = list[f]["audio_codec"];
													var video = list[f]["video_codec"];
													Janus.debug("  >> [" + id + "] " + display + " (audio: " + audio + ", video: " + video + ")");
													newRemoteFeed(id, display, audio, video);
												}
											} else if(msg["leaving"]) {
												// One of the publishers has gone away?
												var leaving = msg["leaving"];
												Janus.log("Publisher left: " + leaving);
												var remoteFeed = null;
												for(var i=1; i<sdk.maxMan; i++) {
													if(feeds[i] && feeds[i].rfid == leaving) {
														remoteFeed = feeds[i];
														break;
													}
												}
												if(remoteFeed != null) {
													Janus.debug("Feed " + remoteFeed.rfid + " (" + remoteFeed.rfdisplay + ") has left the room, detaching");

													if(sdk.callback)
														sdk.callback(SZW_user_leave, remoteFeed.rfdisplay);
													feeds[remoteFeed.rfindex] = null;
													remoteFeed.detach();
												}
											} else if(msg["unpublished"]) {
												// One of the publishers has unpublished?
												var unpublished = msg["unpublished"];
												Janus.log("Publisher left: " + unpublished);
												if(unpublished === 'ok') {
													// That's us
													sfutest.hangup();
													return;
												}
												var remoteFeed = null;
												for(var i=1; i<sdk.maxMan; i++) {
													if(feeds[i] && feeds[i].rfid == unpublished) {
														remoteFeed = feeds[i];
														break;
													}
												}
												if(remoteFeed != null) {
													Janus.debug("Feed " + remoteFeed.rfid + " (" + remoteFeed.rfdisplay + ") has left the room, detaching");

													if(sdk.callback)
														sdk.callback(SZW_user_leave, remoteFeed.rfdisplay);
													feeds[remoteFeed.rfindex] = null;
													remoteFeed.detach();
												}
											} else if(msg["error"]) {
												if(msg["error_code"] === 426) {
													if(sdk.callback)
														sdk.callback(SZW_error_noRoom, "no such room:" + myroom); //self joined.

													// This is a "no such room" error: give a more meaningful description

												} else {
													if(sdk.callback)
														sdk.callback(SZW_unknownError, "unknown error"); //self joined.
												}
											}
										}
									}
									if(jsep) {
										Janus.debug("Handling SDP as well...", jsep);
										sfutest.handleRemoteJsep({ jsep: jsep });
										// Check if any of the media we wanted to publish has
										// been rejected (e.g., wrong or unsupported codec)
										var audio = msg["audio_codec"];
										if(mystream && mystream.getAudioTracks() && mystream.getAudioTracks().length > 0 && !audio) {
											// Audio has been rejected
											if(sdk.callback)
													sdk.callback(SZW_unknownError, "Our audio stream has been rejected, viewers won't hear us"); //self joined.
											Janus.log("Our audio stream has been rejected, viewers won't hear us");
										}
										var video = msg["video_codec"];
										if(mystream && mystream.getVideoTracks() && mystream.getVideoTracks().length > 0 && !video) {
											// Video has been rejected
											if(sdk.callback)
													sdk.callback(SZW_unknownError, "Our video stream has been rejected, viewers won't see us"); //self joined.
											Janus.log("Our video stream has been rejected, viewers won't see us");
											// Hide the webcam video
										}
									}
								},
								onlocalstream: function(stream) {
									Janus.debug(" ::: Got a local stream :::", stream);
									mystream = stream;
									var divRender;
									if(sdk.callback)
										divRender = sdk.callback(SZW_user_enter, myusername); //self joined.
									///use outside component
									Janus.attachMediaStream(divRender.get(0), stream);
									if(sfutest.webrtcStuff.pc.iceConnectionState !== "completed" &&
											sfutest.webrtcStuff.pc.iceConnectionState !== "connected") {
										Janus.log("connected local stream:" + stream);
									}
									var videoTracks = stream.getVideoTracks();
									if(!videoTracks || videoTracks.length === 0){
										Janus.log("no webcam found, is there any?");
										if(sdk.callback)
											sdk.callback(SZW_error_device, "no webcam found, is there any?"); //self joined.
									}
										// No webcam
								},
								onremotestream: function(stream) {
									// The publisher stream is sendonly, we don't expect anything here
								},
								oncleanup: function() {
									Janus.log(" ::: Got a cleanup notification: we are unpublished now :::");
									mystream = null;
									if(sdk.callback)
										sdk.callback(SZW_room_destroy, " ::: Got a cleanup notification: we are unpublished now :::");
								}
							});
					},
					error: function(error) {
						Janus.error(error);
						if(sdk.callback)
							sdk.callback(SZW_unknownError, error);

					},
					destroyed: function() {
						Janus.log(" ::: Got a destroy notification: we are destroyed now :::");
						selfJanusId = 0;
						selfSessionId = 0;
						selfHandler = 0;
						selfRoomId = 0;
						if(sdk.callback)
							sdk.callback(SZW_room_destroy, " ::: Got a destroy notification: we are destroyed now :::");
					}
				});
	}});

}

function publishOwnFeed(useAudio) {
	// Publish our stream
	sfutest.createOffer(
		{
			// Add data:true here if you want to publish datachannels as well
			media: { audioRecv: false, videoRecv: false, audioSend: useAudio, videoSend: true },	// Publishers are sendonly
			// If you want to test simulcasting (Chrome and Firefox only), then
			// pass a ?simulcast=true when opening this demo page: it will turn
			// the following 'simulcast' property to pass to janus.js to true
			simulcast: doSimulcast,
			simulcast2: doSimulcast2,
			success: function(jsep) {
				Janus.debug("Got publisher SDP!", jsep);
				var publish = { request: "configure", audio: useAudio, video: true };
				// You can force a specific codec to use when publishing by using the
				// audiocodec and videocodec properties, for instance:
				// 		publish["audiocodec"] = "opus"
				// to force Opus as the audio codec to use, or:
				// 		publish["videocodec"] = "vp9"
				// to force VP9 as the videocodec to use. In both case, though, forcing
				// a codec will only work if: (1) the codec is actually in the SDP (and
				// so the browser supports it), and (2) the codec is in the list of
				// allowed codecs in a room. With respect to the point (2) above,
				// refer to the text in janus.plugin.videoroom.jcfg for more details
				sfutest.send({ message: publish, jsep: jsep });
			},
			error: function(error) {
				Janus.error("WebRTC error:", error);
				if(useAudio) {
					 publishOwnFeed(false);
				} else {
					if(sdk.callback)
						sdk.callback(SZW_unknownError, error);
				}
			}
		});
}


function newRemoteFeed(id, display, audio, video) {
	// A new feed has been published, create a new plugin handle and attach to it as a subscriber
	var divShow = null;
	var remoteFeed = null;
	janus.attach(
		{
			plugin: "janus.plugin.videoroom",
			opaqueId: opaqueId,
			success: function(pluginHandle) {
				remoteFeed = pluginHandle;
				remoteFeed.simulcastStarted = false;
				Janus.log("Plugin attached! (" + remoteFeed.getPlugin() + ", id=" + remoteFeed.getId() + ")");
				Janus.log("  -- This is a subscriber");
				// We wait for the plugin to send us an offer
				var subscribe = {
					request: "join",
					room: myroom,
					ptype: "subscriber",
					feed: id,
					private_id: mypvtid
				};
				// In case you don't want to receive audio, video or data, even if the
				// publisher is sending them, set the 'offer_audio', 'offer_video' or
				// 'offer_data' properties to false (they're true by default), e.g.:
				// 		subscribe["offer_video"] = false;
				// For example, if the publisher is VP8 and this is Safari, let's avoid video
				if(Janus.webRTCAdapter.browserDetails.browser === "safari" &&
						(video === "vp9" || (video === "vp8" && !Janus.safariVp8))) {
					if(video)
						video = video.toUpperCase()
					subscribe["offer_video"] = false;
				}
				remoteFeed.videoCodec = video;
				remoteFeed.send({ message: subscribe });
			},
			error: function(error) {
				Janus.error("  -- Error attaching plugin...", error);
			},
			onmessage: function(msg, jsep) {
				Janus.debug(" ::: Got a message (subscriber) :::", msg);
				var event = msg["videoroom"];
				Janus.debug("Event: " + event);
				if(msg["error"]) {
					Janus.log("error occured, Event: " + event);
				} else if(event) {
					if(event === "attached") {
						// Subscriber created and attached
						for(var i=1;i<sdk.maxMan;i++) {
							if(!feeds[i]) {
								feeds[i] = remoteFeed;
								remoteFeed.rfindex = i;
								break;
							}
						}
						remoteFeed.rfid = msg["id"];
						remoteFeed.rfdisplay = msg["display"];

						///get the div from outside
						if(sdk.callback)
							remoteFeed.divShow = sdk.callback(SZW_user_enter, remoteFeed.rfdisplay);
						Janus.log("Successfully attached to feed " + remoteFeed.rfid + " (" + remoteFeed.rfdisplay + ") in room " + msg["room"]);
					} else if(event === "event") {
						// Check if we got a simulcast-related event from this publisher
						var substream = msg["substream"];
						var temporal = msg["temporal"];
						if((substream !== null && substream !== undefined) || (temporal !== null && temporal !== undefined)) {
							if(!remoteFeed.simulcastStarted) {
								remoteFeed.simulcastStarted = true;
								// Add some new buttons
								addSimulcastButtons(remoteFeed.rfindex, remoteFeed.videoCodec === "vp8" || remoteFeed.videoCodec === "h264");
							}
							// We just received notice that there's been a switch, update the buttons
							updateSimulcastButtons(remoteFeed.rfindex, substream, temporal);
						}
					} else {
						// What has just happened?
					}
				}
				if(jsep) {
					Janus.debug("Handling SDP as well...", jsep);
					// Answer and attach
					remoteFeed.createAnswer(
						{
							jsep: jsep,
							// Add data:true here if you want to subscribe to datachannels as well
							// (obviously only works if the publisher offered them in the first place)
							media: { audioSend: false, videoSend: false },	// We want recvonly audio/video
							success: function(jsep) {
								Janus.debug("Got SDP!", jsep);
								var body = { request: "start", room: myroom };
								remoteFeed.send({ message: body, jsep: jsep });
							},
							error: function(error) {
								Janus.error("WebRTC error:", error);
								if(sdk.callback)
									sdk.callback(SZW_unknownError, "WebRTC error:" + error);
							}
						});
				}
			},
			iceState: function(state) {
				Janus.log("ICE state of this WebRTC PeerConnection (feed #" + remoteFeed.rfindex + ") changed to " + state);
			},
			webrtcState: function(on) {
				Janus.log("Janus says this WebRTC PeerConnection (feed #" + remoteFeed.rfindex + ") is " + (on ? "up" : "down") + " now");
			},
			onlocalstream: function(stream) {
				// The subscriber stream is recvonly, we don't expect anything here
			},
			onremotestream: function(stream) {
				Janus.debug("Remote feed #" + remoteFeed.rfindex + ", stream:", stream);
				var addButtons = false;
				if($(remoteFeed.divShow).length === 0) {
					addButtons = true;
				}
				Janus.attachMediaStream($(remoteFeed.divShow).get(0), stream);
				var videoTracks = stream.getVideoTracks();
				if(!videoTracks || videoTracks.length === 0) {
					// No remote video
					if(sdk.callback)
						sdk.callback(SZW_unknownError, "although there is one remote stream ,but no video.");
				} else {
					///show the video
				}
				if(!addButtons)
					return;
				if(Janus.webRTCAdapter.browserDetails.browser === "chrome" || Janus.webRTCAdapter.browserDetails.browser === "firefox" ||
						Janus.webRTCAdapter.browserDetails.browser === "safari") {
					///originally for bitrate update
				}
			},
			oncleanup: function() {
				Janus.log(" ::: Got a cleanup notification (remote feed " + id + ") :::");
			}
		});
}
function _isMuted() {
	Janus.warn(" only for local mute status");
	//if(userId !== myusername)
	//{
	//	console("the muting status of others is not supported yet. please contact admin for further info.");
	//	return;
	//}
	return sfutest.isAudioMuted();
}

function _isVideoMuted() {
	Janus.warn(" only for local video mute status");
	//if(userId !== myusername)
	//{
	//	console("the muting video status of others is not supported yet. please contact admin for further info.");
	//	return;
	//}
	return sfutest.isVideoMuted();
}
///////////////////////////////////////////
//for stopping desktop sharing
function unpublishOwnScreenFeed() {
	// Unpublish desktop stream
	var unpublish = { request: "unpublish" };
	screentest.send({ message: unpublish });
	screentest = null;
}
////////////////////////////////////////////
function publishScreenShare()
{
	//start screenshare
	janus.attach(
	{
		plugin: "janus.plugin.videoroom",
		opaqueId: opaqueIdScreen,
		success: function(pluginHandle) {
			screentest = pluginHandle;
			Janus.log("screen Plugin attached! (" + screentest.getPlugin() + ", id=" + screentest.getId() + ")");
			// Prepare the username registration, display name is like roomid_screenShare_usrId_sessionId.

			var register = {
				request: "join",
				room: selfRoomId,
				ptype: "publisher",
				display: screenUsr
			};
			screentest.send({ message: register });
			capture = "screen";
		},
		error: function(error) {
			Janus.error("screenshare :::   -- Error attaching screen plugin...", error);
		},
		consentDialog: function(on) {
			Janus.debug("screenshare :::  Consent dialog should be " + (on ? "on" : "off") + " now");
		},
		iceState: function(state) {
			Janus.log("screenshare ::: ICE state changed to " + state);
		},
		mediaState: function(medium, on) {
			Janus.log("screenshare ::: Janus " + (on ? "started" : "stopped") + " receiving our " + medium);
		},
		webrtcState: function(on) {
			Janus.log("screenshare ::: Janus says this WebRTC PeerConnection screenshare is " + (on ? "up" : "down") + " now");
		},
		onmessage: function(msg, jsep) {
			Janus.debug("screenshare ::: Got a message (publisher) :::", msg);
			var event = msg["videoroom"];
			Janus.debug("Event: " + event);
			if(event) {
				if(event === "joined") {
					myid = msg["id"];
					Janus.log("screenshare ::: Successfully joined room " + msg["room"] + " with ID " + myid);
					//we just publisher,
					// This is our session, publish our stream
					Janus.debug(" screenshare Negotiating WebRTC stream for our screen (capture " + capture + ")");
					// Safari expects a user gesture to share the screen: see issue #2455
					if(Janus.webRTCAdapter.browserDetails.browser === "safari") {
						screentest.createOffer(
							{
								media: { video: capture, audioSend: false, videoRecv: false},	// Screen sharing Publishers are sendonly
								success: function(jsep) {
									Janus.debug("screenshare ::: Got publisher SDP!", jsep);
									var publish = { request: "configure", audio: false, video: true };
									screentest.send({ message: publish, jsep: jsep });
								},
								error: function(error) {
									Janus.error("screenshare ::: WebRTC error:", error);
								}
							});
					} else {
						// Other browsers should be fine, we try to call getDisplayMedia directly
						screentest.createOffer(
							{
								media: { video: capture, audioSend: false, videoRecv: false},	// Screen sharing Publishers are sendonly
								success: function(jsep) {
									Janus.debug("screenshare ::: Got publisher SDP!", jsep);
									var publish = { request: "configure", audio: false, video: true };
									screentest.send({ message: publish, jsep: jsep });
								},
								error: function(error) {
									Janus.error("screenshare ::: WebRTC error:", error);
								}
							});
					}
					///notify mgr to create push
					Janus.log("before notification: selfSession=" + selfSessionId + ", selfHandler=" + screentest.getId() + ", selfJanusId=" + myid + ", selfRoomId=" + selfRoomId + ", projectId=" + sdk.projectId + ", outside usrId=" + screenUsr);
					//调用MGR
					var params = "selfHandler=" + screentest.getId() + "&selfRoomId=" + selfRoomId + "&selfSession=" + selfSessionId + "&outsideUserId=" + screenUsr + "&selfPublishId=" + myid + "&projectId=" + sdk.projectId;// + "&appId=" + appId;
					var signature = _md5(params + "&");
					$.get(apis.getPublishStream + params + "&" + signature, function(data,status){
						if(data !=="" && (data.result === "success")){
							suc(true);
						}
						else
						{
							Janus.error("failed to getPublishedStream");
						}
					});
				} else if(event === "event") {
					// leave it to common publisher.
					if(msg["publishers"]) {
						var list = msg["publishers"];
						Janus.debug("screenshare Got a list of available publishers/feeds:", list);
						for(var f in list) {
							var id = list[f]["id"];
							var display = list[f]["display"];
							var audio = list[f]["audio_codec"];
							var video = list[f]["video_codec"];
							Janus.debug("screenshare :::   >> [" + id + "] " + display + " (audio: " + audio + ", video: " + video + ")");
						}
					}
				}
			}
			if(jsep) {
				Janus.debug("screenshare ::: Handling SDP as well...", jsep);
				screentest.handleRemoteJsep({ jsep: jsep });
			}
		},
		onlocalstream: function(stream) {
			Janus.debug("screenshare ::: Got a local stream :::", stream);
			var screenRender;
			if(sdk.callback)
				divRender = sdk.callback(SZW_user_enter, screenUsr); //self screen share joined.
			Janus.attachMediaStream(divRender.get(0), stream);
		},
		onremotestream: function(stream) {
			// The publisher stream is sendonly, we don't expect anything here
		},
		oncleanup: function() {
			Janus.log("screenshare ::: Got a cleanup notification :::");
		}
	});
}
////////////////////////////////////////////
function _screenShare(usrId, bStart, suc, err)
{
	if(janus === null)
	{
		console.error("screenshare ::: streaming core has not inited, screenshare should be called after meeting inited.");
		return;
	}
	if(bStart === 1 && screentest !== null)
	{
		console.warn("screenshare ::: screenshare has started. to restart it, stop it at first");
		return;
	}
	if(bStart ===1)
	{
		screenUsr = selfRoomId + "_screenShare_" + myusername + "_" + sdk.projectId;
		//TODO call add user
		var paramsUsr = {
			projectId: sdk.projectId,
			userIds: [screenUsr]
		};
		//call start stream
		var params = "userId=" + screenUsr + "&userToken=&videoType=3&userType=0&projectId=" + sdk.projectId + "&roomId=&roomName=&";
		var signature = _md5(params);
		params += signature;
		var api = apis.getRtcRoom + params;
		//调用服务端接口完成业务处理
		$.get(api,function(data,status){
			if(data !==""){
				var ret = data;
				if(ret.result !== "success")
				{
					Janus.log("failed to get room from mgr");
					suc(false);
					return;
				}
				suc(true);  //for roomid,
				Janus.log("screenshare :::  got: roomid=" + ret.videoInfo.webrtcRoomId + ", serverIn=" + ret.videoInfo.webrtcServer);
				////
				publishScreenShare();
			}
		});
	}
	else if(bStart === 0)
	{
		///let us stop it.
		Janus.log("screenshare ::: stop our screenshare.");
		unpublishOwnScreenFeed();
		//TODO call stopStream.
		//调用MGR
		var params = "projectId=" + sdk.projectId + "&roomId=" + selfRoomId + "&userId=" + screenUsr;
		var signature = _md5(params + "&");
		$.get(apis.getStopStream + params + "&" + signature, function(data,status){
			   if(data !=="" && (data.result === "success")){
			         suc(true);
			   }
			   else
        	   {
				Janus.error("screenshare ::: failed to getStopStream");
			   }
		});
		return;
	}
	else
	{
		console.error("screenshare ::: bstart 1 means starting, 0 means stopping, bstart=" + bstart );
		return;
	}
}
//////////////////////////////////////

		//外部请求接口
		return {
			init                 : _init,
			unInit               : _unInit,
			createRoom           : _createRoom,
			destroyRoom          : _destroyRoom,
			startPushStream      : _startPushStream,
			startPushStreamV2    : _startPushStreamV2,
			stopPushStream       : _stopPushStream,
			startMixStream       : _startMixStream,
			stopMixStream        : _stopMixStream,
			getProjectLiveUrls   : _getProjectLiveUrls,
			getProjectReviewUrls : _getProjectReviewUrls ,
			queryDevices         : _queryDevices,
			setStatusCallback    : _setStatusCallback,
			screenShare          : _screenShare,
			mute           		 : _mute,
			toggleMute           : _toggleMute, //obsoleted.
			isMuted		     	 : _isMuted,
			videoMute      		 : _videoMute,
			toggleVideoMute      : _toggleVideoMute,//obsoleted.
			isVideoMuted		 : _isVideoMuted,
			unpublish	         : _unpublish,
		}
})();
